
package ky.shred;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.StatFs;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;

public class AnShred extends Activity {

    private EditText mShredCountEditText;
    private CheckBox mInternalCheckBox;
    private ProgressBar mInternalProgrssBar;
    private CheckBox mExternalCheckBox;
    private ProgressBar mExternalProgressBar;
    private Button mButton;
    private TextView mResultHint;

    private int mShredCount = 0;
    private int mState = 0;
    private static final int STATE_IDLE = 0;
    private static final int STATE_SHRED = 1;

    private static final int PRORESS_MAX = 100;

    private static final int BUFFER_BLOCK = 10;
    private static final int FILE_LEN = 10 * 1024 * 1024;

    private static final String CACHE_FOLDER = "shred";

    private ShredTask mInternalTask;
    private ShredTask mExternalTask;

    private class ShredTask extends AsyncTask<Integer, Integer, Integer> {
        static final int ERROR_MKDIR = 1;
        static final int ERROR_CANCEL = 2;

        boolean cancel = false;
        boolean finish = false;
        String path = null;
        ProgressBar progressBar = null;

        void setPath(String path) {
            this.path = path;
        }

        void setProgressBar(ProgressBar bar) {
            progressBar = bar;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Integer doInBackground(Integer... values) {
            int count = values[0];
            long size = 0;
            long total = 0;
            long recent = 0;
            byte[] buffer = null;

            File folder = new File(path, CACHE_FOLDER);
            if (folder.exists()) {
                deleteFile(folder);
            }

            String path = folder.getPath();
            if (folder.mkdir()) {
                size = getBlockSize(path);
                total = getAvailableBlocks(path);
                recent = total;
                buffer = new byte[(int) (BUFFER_BLOCK * size)];
            } else {
                return ERROR_MKDIR;
            }

            while (!cancel && count > 0) {
                byte b = 0;
                if (count % 2 == 0) {
                    b = 0;
                } else {
                    b = -1;
                }

                for (int i = 0; i < buffer.length; i++) {
                    buffer[i] = b;
                }

                if (folder.exists()) {
                    deleteFile(folder);
                }

                if (folder.mkdir()) {
                    long i = 0;
                    while (!cancel && (recent = getAvailableBlocks(path)) > 0) {
                        int progress = (int) (PRORESS_MAX * (total - recent) / total);
                        publishProgress(progress);
                        FileOutputStream fos = null;
                        try {
                            File file = new File(folder, String.valueOf(i));
                            int len = (int) Math.min(recent * size, FILE_LEN);
                            fos = new FileOutputStream(file);
                            int writeLen = 0;
                            while (!cancel && (writeLen = Math.min(buffer.length, len)) > 0) {
                                fos.write(buffer, 0, writeLen);
                                len -= writeLen;
                            }
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                fos.close();
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }

                        i++;
                    }
                }

                count--;
            }

            if (folder.exists()) {
                deleteFile(folder);
            }

            if (cancel) {
                return ERROR_CANCEL;
            }

            return 0;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (progressBar != null) {
                progressBar.setProgress(values[0]);
            }
        }

        @Override
        protected void onPostExecute(Integer result) {
            super.onPostExecute(result);
            finish = true;
            onFinishShred();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_an_shred);

        intView();
        checkViewState();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        // getMenuInflater().inflate(R.menu.an_shred, menu);
        return false;
    }

    @Override
    public void onDestroy() {
        stopShredTask();
        super.onDestroy();
    }

    private void intView() {
        mShredCountEditText = (EditText) findViewById(R.id.shred_count);

        mInternalCheckBox = (CheckBox) findViewById(R.id.internal_storage);
        mInternalProgrssBar = (ProgressBar) findViewById(R.id.internal_progress);
        mInternalProgrssBar.setMax(PRORESS_MAX);

        mExternalCheckBox = (CheckBox) findViewById(R.id.external_storage);
        mExternalProgressBar = (ProgressBar) findViewById(R.id.external_progress);
        mExternalProgressBar.setMax(PRORESS_MAX);

        mButton = (Button) findViewById(R.id.button);
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mState == STATE_IDLE) {
                    startShred();
                } else if (mState == STATE_SHRED) {
                    cancelShred();
                }
            }
        });

        mResultHint = (TextView) findViewById(R.id.result_hint);
    }

    private void onFinishShred() {
        if ((mInternalTask == null || mInternalTask.finish)
                && (mExternalTask == null || mExternalTask.finish)) {
            mInternalTask = null;
            mExternalTask = null;
            mState = STATE_IDLE;
            checkViewState();
        }
    }

    private void stopShredTask() {
        if (mInternalTask != null) {
            mInternalTask.cancel = true;
            mInternalTask.progressBar = null;
            mInternalTask = null;
        }

        if (mExternalTask != null) {
            mExternalTask.cancel = true;
            mExternalTask.progressBar = null;
            mExternalTask = null;
        }
    }

    private void cancelShred() {
        stopShredTask();

        mState = STATE_IDLE;
        checkViewState();
    }

    private void startShred() {
        stopShredTask();

        mState = STATE_IDLE;

        mShredCount = 0;
        try {
            mShredCount = Integer.valueOf(mShredCountEditText.getText()
                    .toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (mShredCount > 0) {
            if (mInternalCheckBox.isChecked()) {
                mInternalTask = new ShredTask();
                File folder = getFilesDir();
                mInternalTask.setPath(folder.getPath());
                mInternalTask.setProgressBar(mInternalProgrssBar);
                mInternalTask.execute(mShredCount);
                mState = STATE_SHRED;
            }

            if (mExternalCheckBox.isChecked()) {
                mExternalTask = new ShredTask();
                File folder = getExternalFilesDir(null);
                mExternalTask.setPath(folder.getPath());
                mExternalTask.setProgressBar(mExternalProgressBar);
                mExternalTask.execute(mShredCount);
                mState = STATE_SHRED;
            }
        }

        checkViewState();
    }

    private void checkViewState() {
        if (mState == STATE_IDLE) {
            mShredCount = 0;
            try {
                mShredCount = Integer.valueOf(mShredCountEditText.getText()
                        .toString());
            } catch (Exception e) {
                e.printStackTrace();
            }

            mShredCountEditText.setEnabled(true);
            mInternalCheckBox.setEnabled(true);
            mInternalProgrssBar.setProgress(0);
            mExternalCheckBox.setEnabled(true);
            mExternalProgressBar.setProgress(0);

            if (mShredCount > 0
                    && (mInternalCheckBox.isChecked() || mExternalCheckBox
                            .isChecked())) {
                mButton.setEnabled(true);
            } else {
                mButton.setEnabled(false);
            }
            mButton.setEnabled(true);
            mButton.setText(R.string.start);
        } else if (mState == STATE_SHRED) {
            mShredCountEditText.setEnabled(false);
            mInternalCheckBox.setEnabled(false);
            mExternalCheckBox.setEnabled(false);

            mButton.setText(R.string.cancel);
            mButton.setEnabled(true);
        }

    }

    private long getBlockSize(String path) {
        StatFs sf = new StatFs(path);
        return sf.getBlockSize();
    }

    private long getAvailableBlocks(String path) {
        StatFs sf = new StatFs(path);
        return sf.getAvailableBlocks();
    }

    private void deleteFile(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File child : files) {
                deleteFile(child);
            }
        }
        file.delete();
    }
}
